package org.example.filter;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import jakarta.annotation.Resource;
import jakarta.servlet.*;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang.StringUtils;
import org.example.dto.base.Result;
import org.example.enums.ResultCodeEnum;
import org.example.util.AESUtil;
import org.example.util.IpUtils;
import org.example.util.JsonUtils;
import org.example.util.MD5Signature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.w3c.dom.css.Counter;

import java.io.IOException;
import java.util.Date;
import java.util.Iterator;
import java.util.Map;

/**
 * @ Author     ：hanxi
 * @ Date       ：Created in 14:52 2024/3/17
 * @ Description：
 */

public class SignFilter implements Filter {

    private static Logger logger = LoggerFactory.getLogger(SignFilter.class);

    @Value("${spring.profiles.active}")
    private String activeEnv;

    @Value("${md5.key}")
    private String md5Key;

    @Value("${aes.key}")
    private String aesKey;

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        logger.info("SignFilter initialized");
    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain chain) throws IOException, ServletException {
        HttpServletRequest request = (HttpServletRequest) servletRequest;
        HttpServletResponse response = (HttpServletResponse) servletResponse;
        String uri = request.getRequestURI();

        //测试环境直接放行
        if (StringUtils.equals(activeEnv, "dev")) {
            chain.doFilter(request, response);
            return;
        }
        //对非验签接口路径放行
        if (!StringUtils.contains(uri, "/app/")) {
            chain.doFilter(request, response);
            return;
        }
        response.setCharacterEncoding("UTF-8");
        String streamContent = IOUtils.toString(request.getInputStream(), "utf-8");
        ParameterRequestWrapper requestWrapper = new ParameterRequestWrapper(request);
        try {
            Object obj = decodeParams(streamContent, requestWrapper);
            if (obj instanceof ParameterRequestWrapper) {
                requestWrapper = (ParameterRequestWrapper) obj;
                chain.doFilter(requestWrapper, response);
            } else {
                response.getWriter().print(JSON.toJSONString(obj));
            }
        } catch (Exception e) {
            response.getWriter().println(JSON.toJSON(new Result(false, ResultCodeEnum.EXCEPTION.getId(), "程序发生异常！")));
            logger.error("程序发生异常！", e);
        }
    }

    @Override
    public void destroy() {
        logger.info("SignFilter destroy");
    }

    /**
     * 解密参数
     *
     * @param requestWrapper
     * @return
     * @throws Exception
     */
    private Object decodeParams(String streamContent, ParameterRequestWrapper requestWrapper) throws Exception {
        //判断签名
        //logger.info("解密前:"+streamContent);
        if (StringUtils.isBlank(streamContent)) {
            logger.warn("streamContent is empty！");
            return new Result(false, ResultCodeEnum.FAIL.getId(), "参数不正确");
        }
        JSONObject jsonObject = JSON.parseObject(streamContent);
        String params = jsonObject.getString("data");
        String md5Sign = jsonObject.getString("sign");
        //验证md5签名
        if (!MD5Signature.verify(params, md5Sign, md5Key)) {
            logger.warn("签名不正确！");
            return new Result(false, ResultCodeEnum.FAIL.getId(), "签名不正确");
        }
        //rsa解密数据
//        params = URLDecoder.decode(params, "UTF-8");
        params = AESUtil.Decrypt(params, aesKey);
        logger.info("解密后:" + params);
        JSONObject paramsObject = JsonUtils.jsonTrim(params);
        Map<String, Object> map = JSON.parseObject(JSON.toJSONString(paramsObject), Map.class);
        requestWrapper.addAllParameters(map);
        if (map != null && map.size() > 0) {
            //map遍历组织request请求的参数
            Iterator<Map.Entry<String, Object>> it = map.entrySet().iterator();
            while (it.hasNext()) {
                Map.Entry<String, Object> entry = it.next();
                if (entry.getValue() instanceof Map) {
                    //参数强制转换成json形式，防止value值为map的情况
                    requestWrapper.addParameter(entry.getKey(), JSON.toJSONString(entry.getValue()));
                } else if (entry.getValue() instanceof String) {
                    requestWrapper.addParameter(entry.getKey(), entry.getValue().toString());
                } else {
                    requestWrapper.addParameter(entry.getKey(), entry.getValue());
                }
            }
        }
        return requestWrapper;
    }

}
